﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace RaptorEngine.Components.CollidableComponent
{
	public enum VolumeType
	{
		Sphere = 0,
		Box
	}
	
	/// <summary>
	/// Handles the information of one boundingVolume. The actual volume and the offset from the entitys center.
	/// </summary>
	public class BoundingVolume
	{
		public VolumeType VolumeType { get; private set; }
		public Vector3 Offset { get; set; }
		public List<int> CollisionTypes { get; set; }
		public bool IsCalculated { get; set; }
		public float Radius { get; private set; }
		public Vector3 Center { get;  private set; }
		public Vector3 Normal { get; private set; }
        public bool IsActive { get; set; }
        public CollisionAction Action { get; set; }

		private BoundingSphere? _sphere;
		public BoundingSphere? Sphere
		{
			get { return _sphere; }
			set
			{
				_sphere = value;
				_box = null;
				VolumeType = VolumeType.Sphere;
			}
		}

		private BoundingBox? _box;
		public BoundingBox? Box
		{
			get { return _box; }
			set 
			{ 
				_box = value;
				_sphere = null;
				VolumeType = VolumeType.Box;
			}
		}

	    /// <summary>
	    /// Creates a BoundingVolume with a sphere.
	    /// </summary>
	    /// <param name="sphere">The boundingSphere</param>
	    /// <param name="offset">The offset from the entitys position</param>
	    /// <param name="collisionType"></param>
	    public BoundingVolume(BoundingSphere sphere, Vector3 offset, int collisionType)
		{
			_sphere = sphere;
			Offset = offset;
			IsCalculated = false;
			Radius = sphere.Radius;
            Center = sphere.Center;
            IsActive = true;
			VolumeType = VolumeType.Sphere;
			CollisionTypes = new List<int>();
			CollisionTypes.Add(collisionType);
		}

	    /// <summary>
	    /// Creates a BoundingVolume with a box. 
	    /// </summary>
	    /// <param name="box">The boundingBox</param>
	    /// <param name="offset">The offset from the entitys position</param>
	    /// <param name="radius"></param>
	    /// <param name="center"></param>
	    /// <param name="collisionType"></param>
	    public BoundingVolume(BoundingBox box, Vector3 offset, float radius, Vector3 center, int collisionType)
		{
			_box = box;
			Offset = offset;
			IsCalculated = false;
			Radius = radius;
            Center = center;
            IsActive = true;
			VolumeType = VolumeType.Box;
			CollisionTypes = new List<int>();
			CollisionTypes.Add(collisionType);
		}

	    /// <summary>
	    /// Creates a BoundingVolume with a box. 
	    /// </summary>
	    /// <param name="box">The boundingBox</param>
	    /// <param name="offset">The offset from the entitys position</param>
	    /// <param name="radius"></param>
	    /// <param name="center"></param>
	    /// <param name="collisionType"></param>
	    /// <param name="normal"></param>
	    public BoundingVolume(BoundingBox box, Vector3 offset, float radius, Vector3 center, int collisionType, Vector3 normal) 
			: this(box, offset, radius, center, collisionType)
		{
			Normal = normal;
		}

	    /// <summary>
	    /// Update the boundingVolume to match a new position for the entity.
	    /// The boundingVolume will keep the same offset it earlier had.
	    /// </summary>
	    /// <param name="center">The position of the entity</param>
	    /// <param name="rotation"></param>
	    public void UpdateBoundingVolume(Vector3 center, Quaternion rotation)
		{

            Center = center;
            Vector3 offset = Offset;
            if (offset != Vector3.Zero)
            {
                offset = (Matrix.CreateTranslation(offset) * Matrix.CreateFromQuaternion(rotation)).Translation;
            }

            if (Sphere.HasValue)
			{
				Sphere = new BoundingSphere(center + offset, Radius);
            }
			else if(Box.HasValue)
			{
				Vector3 radius = (_box.Value.Max - _box.Value.Min) / 2;
				Vector3 min = center - radius;
                Vector3 max = center + radius;
				Box = new BoundingBox(min, max);
			}
		}

		public void AddCollisionType(int collisionType)
		{
			CollisionTypes.Add(collisionType);
		}
	}
}
